﻿using System;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using Microsoft.Data.ConnectionUI;

namespace AdHocReports.DataSourceEditor
{
    public partial class MainUI : Form
    {
        OleDBConnectionProperties cp;
        private string _targetDirectory = string.Empty;

        public MainUI(string targetDirectory)
        {
            if (!Directory.Exists(targetDirectory))
            {
                Environment.Exit(2);
            }

            InitializeComponent();

            if (!targetDirectory.EndsWith("\\"))
            {
                targetDirectory += "\\";
            }

            _targetDirectory = targetDirectory;

            cp = new OleDBConnectionProperties();
            cp.ConnectionStringBuilder.Add("Provider", "SQLOLEDB");
            oleDBConnectionUIControl.Initialize(cp);
            oleDBConnectionUIControl.LoadProperties();

            InitializeRestrictions();
        }

        private void InitializeRestrictions()
        {
            CheckBox allowSavingPasswordCheckBox = GetControl<CheckBox>("allowSavingPasswordCheckBox");
            if (allowSavingPasswordCheckBox != null)
            {
                allowSavingPasswordCheckBox.Checked = true;
                allowSavingPasswordCheckBox.Enabled = false;
            }

            RadioButton integratedSecurityRadioButton = GetControl<RadioButton>("integratedSecurityRadioButton");
            if (integratedSecurityRadioButton != null)
            {
                integratedSecurityRadioButton.Checked = true;
            }

            ComboBox providerComboBox = GetControl<ComboBox>("providerComboBox");
            if (providerComboBox != null)
            {
                providerComboBox.Enabled = false;
            }

            Button dataLinksButton = GetControl<Button>("dataLinksButton");
            if (dataLinksButton != null)
            {
                dataLinksButton.Enabled = false;
            }
        }

        private T GetControl<T>(string name) where T : class
        {
            T result = null;
            Control[] controls = Controls.Find(name, true);

            if ((controls != null) && (controls.Length == 1))
            {
                result = controls[0] as T;
            }

            return result;
        }

        private void AddDataSource()
        {
            XmlDocument config = new XmlDocument();

            config.Load(_targetDirectory + "web.config");

            XmlNode node = config.SelectSingleNode("configuration/connectionStrings");

            XmlElement connection = config.CreateElement("add");
            XmlAttribute name = config.CreateAttribute("name");
            XmlAttribute connectionString = config.CreateAttribute("connectionString");
            XmlAttribute providerName = config.CreateAttribute("providerName");

            name.Value = "AdHocReports.Properties.Settings.UserDataSource" + node.ChildNodes.Count.ToString();
            connectionString.Value = cp.ConnectionStringBuilder.ToString();
            providerName.Value = "System.Data.OleDb";

            connection.Attributes.Append(name);
            connection.Attributes.Append(connectionString);
            connection.Attributes.Append(providerName);

            node.AppendChild(connection);

            config.Save(_targetDirectory + "web.config");
        }

        private void okButton_Click(object sender, EventArgs e)
        {
            if (SaveConnection())
            {
                Close();
                Environment.ExitCode = 0;
            }
        }

        private bool SaveConnection()
        {
            bool result = false;
            Enabled = false;
            Cursor = Cursors.WaitCursor;
            string error = string.Empty;

            if (IsConnectionGood(ref error))
            {
                if ((HasViews()) || (MessageBox.Show(this, "Views are not defined in this database. Would you like to proceed?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes))
                {
                    AddDataSource();
                    result = true;
                }
            }
            else
            {
                MessageBox.Show(this, "Unable to save connection: " + error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            Cursor = Cursors.Default;
            Enabled = true;

            return result;
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            Close();
            Environment.ExitCode = 1;
        }

        private void testButton_Click(object sender, EventArgs e)
        {
            TestConnection();
        }

        private void TestConnection()
        {
            Enabled = false;
            Cursor = Cursors.WaitCursor;
            string error = string.Empty;

            if (IsConnectionGood(ref error))
            {
                MessageBox.Show(this, "Connected successfully.");
            }
            else
            {
                MessageBox.Show(this, error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            Cursor = Cursors.Default;
            Enabled = true;
        }

        private bool HasViews()
        {
            bool result = false;

            using (OleDbConnection connection = new OleDbConnection(cp.ConnectionStringBuilder.ToString()))
            {
                connection.Open();
                using (DataTable views = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "VIEW" }))
                {
                    result = views.Rows.Count > 0;
                }
            }

            return result;
        }

        private bool IsConnectionGood(ref string error)
        {
            bool result = false;

            using (OleDbConnection connection = new OleDbConnection(cp.ConnectionStringBuilder.ToString()))
            {
                try
                {
                    connection.Open();
                    result = true;
                }
                catch (Exception ex)
                {
                    error = ex.Message;
                }
                finally
                {
                    if (connection.State == ConnectionState.Open)
                    {
                        connection.Close();
                    }
                }
            }

            return result;
        }
    }
}
